package com.example.makerspace.manager;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.example.makerspace.dao.CompetitionDAO;
import com.example.makerspace.domain.CompetitionDO;
import com.example.makerspace.dto.*;
import com.example.makerspace.enums.ResultCodeEnum;
import com.example.makerspace.utils.DateUtils;
import com.example.makerspace.utils.MakerSpaceMapUtils;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static com.example.makerspace.service.impl.AdminServiceImpl.managerMap;


@Component
public class CompetitionManager extends BaseManager<CompetitionDO, CompetitionDTO>{

    @Resource
    private CompetitionDAO competitionDAO;

    @PostConstruct
    public void init(){
        this.baseDAO = competitionDAO;
        managerMap.put("competition", this);
    }

    @Override
    public Result add(Map<String, Object> params,boolean mark) {
        CompetitionDTO competitionDTO = null;
        try {
            competitionDTO = MakerSpaceMapUtils.mapToObj(params, CompetitionDTO.class);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        String title = competitionDTO.getTitle();
        CompetitionDO oldCompetitionDO = competitionDAO.selectByTitle(title);
        if(oldCompetitionDO != null){
            return Result.error(ResultCodeEnum.COMPETITION_EXIST);
        }
        CompetitionDO competitionDO = new CompetitionDO();
        BeanUtils.copyProperties(competitionDTO, competitionDO);
        Optional.ofNullable(competitionDTO.getStartTime()).ifPresent(startTime ->{
            competitionDO.setStartTime(startTime);

        });
        Optional.ofNullable(competitionDTO.getEndTime()).ifPresent(endTime ->{
            competitionDO.setEndTime(endTime);
        });
        return addDO(competitionDO);
    }

    @Override
    protected CompetitionDTO convert2DTO(CompetitionDO competitionDO) {
        if(competitionDO == null){
            return new CompetitionDTO();
        }
        CompetitionDTO competitionDTO = super.convert2DTO(competitionDO);
        Optional.ofNullable(competitionDO.getStartTime()).ifPresent(startTime ->{
            competitionDTO.setStartTime(startTime);
        });
        Optional.ofNullable(competitionDO.getEndTime()).ifPresent(endTime ->{
            competitionDTO.setEndTime(endTime);
        });
        return competitionDTO;
    }

    @Override
    public Result update(Map<String, Object> params) {
        CompetitionDTO competitionDTO = null;
        try {
            competitionDTO = MakerSpaceMapUtils.mapToObj(params, CompetitionDTO.class);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        Integer id = competitionDTO.getId();
        CompetitionDO competitionDO= competitionDAO.selectById(id);
        if(competitionDO == null){
            return Result.error(ResultCodeEnum.COMPETITION_NOT_EXIST);
        }
        Optional.ofNullable(competitionDTO.getTitle()).ifPresent(competitionDO::setTitle);
        Optional.ofNullable(competitionDTO.getContent()).ifPresent(competitionDO::setContent);
        Optional.ofNullable(competitionDTO.getMetrics()).ifPresent(competitionDO::setMetrics);
        Optional.ofNullable(competitionDTO.getQualityStandards()).ifPresent(competitionDO::setQualityStandards);
        Optional.ofNullable(competitionDTO.getOtherReq()).ifPresent(competitionDO::setOtherReq);
        Optional.ofNullable(competitionDTO.getOutcomeFormat()).ifPresent(competitionDO::setOutcomeFormat);
        Optional.ofNullable(competitionDTO.getIpOwner()).ifPresent(competitionDO::setIpOwner);
        Optional.ofNullable(competitionDTO.getEvaluationMethod()).ifPresent(competitionDO::setEvaluationMethod);
        Optional.ofNullable(competitionDTO.getStartTime()).ifPresent(startTime ->{
            competitionDO.setStartTime(startTime);

        });
        Optional.ofNullable(competitionDTO.getEndTime()).ifPresent(endTime ->{
            competitionDO.setEndTime(endTime);
        });
        Optional.ofNullable(competitionDTO.getCompetitionParentId()).ifPresent(competitionDO::setCompetitionParentId);
        return updateDO(competitionDO);
    }


    public PageResult presentCompetition(PageRequest pageRequest) {
        IPage<CompetitionDO> page = competitionDAO.presentCompetitions(pageRequest);
        List<CompetitionDO> records = page.getRecords();
        List<CompetitionDTO> dtoList = Optional.ofNullable(records).orElse(Collections.emptyList())
                .stream().sorted((o1, o2) -> o2.getCreateTime().compareTo(o1.getCreateTime()))
                .map(this::convert2DTO)
                .collect(Collectors.toList());
        PageResult pageResult = PageResult.success();
        pageResult.setObj(dtoList);
        pageResult.setPagination(new Pagination(dtoList.size(), page.getCurrent(), page.getTotal(), page.getPages()));
        return pageResult;
    }

    public Result detail(Map<String, Object> params) {
        Integer competitionID = MapUtils.getInteger(params, "competition");
        if(competitionID == null){
            return Result.success();
        }
        CompetitionDO competitionDO = competitionDAO.selectById(competitionID);
        return Result.success(convert2DTO(competitionDO));
    }

    public CompetitionDTO detailByID(Integer id){
        return convert2DTO(competitionDAO.selectById(id));
    }
}
